package com.gzhryc.shared_device.oem.code.member.services;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.NumberTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.base.IMemberBusinessService;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.bxscn.code.dao.db.BXSCNOrder;
import com.gzhryc.shared_device.bxscn.code.dao.db.BXSCNShopOrder;
import com.gzhryc.shared_device.bxscn.code.dao.enums.BXSCNOrderEnum;
import com.gzhryc.shared_device.bxscn.code.dao.enums.BXSCNShopOrderEnum;
import com.gzhryc.shared_device.bxscn.code.dao.enums.EBXSCNCostMode;
import com.gzhryc.shared_device.cdb.code.dao.db.CDBOrder;
import com.gzhryc.shared_device.cdb.code.dao.enums.CDBOrderEnum;
import com.gzhryc.shared_device.cdcz.code.dao.db.CDCZOrder;
import com.gzhryc.shared_device.cdcz.code.dao.enums.CDCZOrderEnum;
import com.gzhryc.shared_device.oem.code.ConfigUtils;
import com.gzhryc.shared_device.oem.code.business.EBusinessType;
import com.gzhryc.shared_device.oem.code.config.BusinessConfig;
import com.gzhryc.shared_device.oem.code.device.EDeviceFunCode;
import com.gzhryc.shared_device.oem.code.member.dao.MemberBusinessOrderDao;
import com.gzhryc.shared_device.oem.code.member.dao.db.MemberBusinessOrder;
import com.gzhryc.shared_device.oem.code.member.dao.enums.MemberBusinessOrderEnum;
import com.gzhryc.shared_device.oem.code.member.services.dto.MemberBusinessOrderSearch;
import com.gzhryc.shared_device.oem.code.profit.service.BusinessOrderUserService;
import com.gzhryc.shared_device.pcl.code.dao.db.PCLOrder;
import com.gzhryc.shared_device.pcl.code.dao.enums.PCLOrderEnum;

import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MemberBusinessOrderService implements IMemberBusinessService {

    static Logger log = Logger.getLogger(MemberBusinessOrderService.class);

    public static MemberBusinessOrderService self(Date date) {
        return MultiDBTools.getService(MemberBusinessOrderService.class, date);
    }

    public static MemberBusinessOrderService self(String jdbcKey,Date date) {
        return MultiDBTools.getService(jdbcKey,MemberBusinessOrderService.class, date);
    }

    MemberBusinessOrderDao dao;

    public MemberBusinessOrderService(String jdbcKey,Date date) {
        dao = new MemberBusinessOrderDao(jdbcKey,date);
    }

    public List<MemberBusinessOrder> findBySearch(MemberBusinessOrderSearch search, Integer pageNo, Integer pageLimit) {
        Conditions conditions = dao.buildConditions(search);
        conditions.and().likeBoth("tradeNo", search.getTrim()).or().likeBoth("placeName", search.getTrim())
                .or().likeBoth("deviceSn", search.getTrim()).or().likeBoth("nickname", search.getTrim());
        conditions.and().in("placeId", search.getPlaceIds());
        conditions.desc("createDate");
        try {
            return dao.findByCondition(conditions, pageNo, pageLimit);
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public List<MemberBusinessOrder> findJoinBySearch(MemberBusinessOrderSearch search, Integer pageNo, Integer pageLimit) {
        Conditions conditions = dao.buildConditions(search);
        conditions.and().likeBoth("tradeNo", search.getTrim()).or().likeBoth("placeName", search.getTrim())
                .or().likeBoth("deviceSn", search.getTrim()).or().likeBoth("nickname", search.getTrim());
        conditions.and().in("placeId", search.getPlaceIds());
        conditions.desc("createDate");
        try {
            return dao.findJoinByCondition(conditions, pageNo, pageLimit);
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public List<MemberBusinessOrder> findByTradeNoList(List<String> tradeNoList) {
        if (tradeNoList != null && tradeNoList.size() > 0) {
            Conditions conditions = new Conditions(MemberBusinessOrder.class);
            conditions.and().in("tradeNo", tradeNoList);
            conditions.desc("createDate");
            try {
                return dao.findByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public Long countBySearch(MemberBusinessOrderSearch search) {
        Conditions conditions = dao.buildConditions(search);
        conditions.and().likeBoth("tradeNo", search.getTrim()).or().likeBoth("placeName", search.getTrim())
                .or().likeBoth("deviceSn", search.getTrim()).or().likeBoth("nickname", search.getTrim());
        conditions.and().in("placeId", search.getPlaceIds());
        try {
            return dao.count(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public Long countJoinBySearch(MemberBusinessOrderSearch search) {
        Conditions conditions = dao.buildConditions(search);
        conditions.and().likeBoth("tradeNo", search.getTrim()).or().likeBoth("placeName", search.getTrim())
                .or().likeBoth("deviceSn", search.getTrim()).or().likeBoth("nickname", search.getTrim());
        conditions.and().in("placeId", search.getPlaceIds());
        try {
            return dao.count(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public MemberBusinessOrder getBySearch(MemberBusinessOrderSearch search) {
        Conditions conditions = dao.buildConditions(search);
        try {
            return dao.get(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public MemberBusinessOrder getByTradeNo(String tradeNo) {
        try {
            return dao.getById(tradeNo);
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public MemberBusinessOrder getByMemberAndTradeNo(Long memberId, String tradeNo) {
        if (memberId != null && StringTools.isNotBlank(tradeNo)) {
            Conditions conditions = new Conditions(MemberBusinessOrder.class);
            conditions.and().is("memberId", memberId);
            conditions.and().is("tradeNo", tradeNo);

            try {
                return dao.get(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public boolean updateAgentIdByPlaceId(Long placeId,Long agentId){
        if(placeId != null){
            Conditions conditions = new Conditions(MemberBusinessOrder.class);
            conditions.and().is("placeId",placeId);

            Map<String,Object> map = new HashMap<>();
            map.put("agentId",agentId);

            try {
                return dao.update(map,conditions) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public MemberBusinessOrder create(CDCZOrder deviceOrder) throws LogicException {
        MemberBusinessOrder businessOrder = ClassTools.copy(new MemberBusinessOrder(), deviceOrder);
        businessOrder.setTitle("共享电源插座充电订单");

        businessOrder.setDeviceTypeName(deviceOrder.getDeviceTypeName());
        businessOrder.setDeviceSn(deviceOrder.getChargeSocketSn());
        businessOrder.setDeviceFunCode(EDeviceFunCode.CDCZ.index());
        businessOrder.setBusinessType(EBusinessType.CDCZ.index());
        businessOrder.setCostModeName(deviceOrder.getCostModeName());  //无属性无法自动拷贝

        businessOrder.setMemberId(deviceOrder.getMemberId());
        businessOrder.setMemberName(deviceOrder.getMemberName());
        businessOrder.setAgentId(deviceOrder.getAgentId());
        businessOrder.setPlaceId(deviceOrder.getPlaceId());
        businessOrder.setPlaceName(deviceOrder.getPlaceName());
        businessOrder.setProvince(deviceOrder.getProvince());
        businessOrder.setCity(deviceOrder.getCity());
        businessOrder.setCityArea(deviceOrder.getCityArea());
        businessOrder.setAreaCode(deviceOrder.getAreaCode());
        businessOrder.setState(MemberBusinessOrderEnum.State.Working.index());

        if (CDCZOrderEnum.PayState.Cancel.index().equals(deviceOrder.getPayState())
                || CDCZOrderEnum.State.Fail.index().equals(deviceOrder.getState())) {
            businessOrder.setState(MemberBusinessOrderEnum.State.Cancel.index());
        } else if (CDCZOrderEnum.State.Finish.index().equals(deviceOrder.getState())
                || CDCZOrderEnum.State.Close.index().equals(deviceOrder.getState())) {
            businessOrder.setState(MemberBusinessOrderEnum.State.Finish.index());
        }

        try {
            if (dao.insert(businessOrder) > 0) {
                return businessOrder;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public MemberBusinessOrder create(CDBOrder deviceOrder) throws LogicException {
        MemberBusinessOrder businessOrder = ClassTools.copy(new MemberBusinessOrder(), deviceOrder);
        businessOrder.setTitle("共享充电宝租借订单");

        businessOrder.setDeviceTypeName(deviceOrder.getLeaseDeviceTypeName());
        businessOrder.setDeviceSn(deviceOrder.getLeaseChargingCabinetSn());
        businessOrder.setDeviceFunCode(EDeviceFunCode.CDB.index());
        businessOrder.setBusinessType(EBusinessType.CDB.index());
        businessOrder.setCostModeName(deviceOrder.getCostModeName());  //无属性无法自动拷贝

        businessOrder.setMemberId(deviceOrder.getMemberId());
        businessOrder.setMemberName(deviceOrder.getMemberName());
        businessOrder.setAgentId(deviceOrder.getLeaseAgentId());
        businessOrder.setPlaceId(deviceOrder.getLeasePlaceId());
        businessOrder.setPlaceName(deviceOrder.getLeasePlaceName());
        businessOrder.setProvince(deviceOrder.getLeaseProvince());
        businessOrder.setCity(deviceOrder.getLeaseCity());
        businessOrder.setCityArea(deviceOrder.getLeaseCityArea());
        businessOrder.setAreaCode(deviceOrder.getLeaseAreaCode());
        businessOrder.setState(MemberBusinessOrderEnum.State.Working.index());

        if (CDBOrderEnum.PayState.Cancel.index().equals(deviceOrder.getPayState())) {
            businessOrder.setState(MemberBusinessOrderEnum.State.Cancel.index());
        } else if (CDBOrderEnum.State.RevertFinish.index().equals(deviceOrder.getState())
                || CDBOrderEnum.State.LeaseFail.index().equals(deviceOrder.getState())
                || CDBOrderEnum.State.Close.index().equals(deviceOrder.getState())) {
            businessOrder.setState(MemberBusinessOrderEnum.State.Finish.index());
        }

        try {
            if (dao.insert(businessOrder) > 0) {
                return businessOrder;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public MemberBusinessOrder create(PCLOrder deviceOrder) throws LogicException {
        MemberBusinessOrder businessOrder = ClassTools.copy(new MemberBusinessOrder(), deviceOrder);
        businessOrder.setTitle("便捷线充订单");

        businessOrder.setDeviceTypeName(deviceOrder.getDeviceTypeName());
        businessOrder.setDeviceSn(deviceOrder.getChargingCableSn());
        businessOrder.setDeviceFunCode(EDeviceFunCode.PCL.index());
        businessOrder.setBusinessType(EBusinessType.PCL.index());
        businessOrder.setCostModeName(deviceOrder.getCostModeName());  //无属性无法自动拷贝

        businessOrder.setMemberId(deviceOrder.getMemberId());
        businessOrder.setMemberName(deviceOrder.getMemberName());
        businessOrder.setAgentId(deviceOrder.getAgentId());
        businessOrder.setPlaceId(deviceOrder.getPlaceId());
        businessOrder.setPlaceName(deviceOrder.getPlaceName());
        businessOrder.setProvince(deviceOrder.getProvince());
        businessOrder.setCity(deviceOrder.getCity());
        businessOrder.setCityArea(deviceOrder.getCityArea());
        businessOrder.setAreaCode(deviceOrder.getAreaCode());
        businessOrder.setState(MemberBusinessOrderEnum.State.Working.index());

        if (PCLOrderEnum.PayState.Cancel.index().equals(deviceOrder.getPayState())) {
            businessOrder.setState(MemberBusinessOrderEnum.State.Cancel.index());
        } else if (PCLOrderEnum.State.Finish.index().equals(deviceOrder.getState())
                || PCLOrderEnum.State.Close.index().equals(deviceOrder.getState())) {
            businessOrder.setState(MemberBusinessOrderEnum.State.Finish.index());
        }

        try {
            if (dao.insert(businessOrder) > 0) {
                return businessOrder;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public MemberBusinessOrder create(BXSCNOrder deviceOrder) throws LogicException {
        MemberBusinessOrder businessOrder = ClassTools.copy(new MemberBusinessOrder(), deviceOrder);
        businessOrder.setTitle("便携式储能电池租借订单");

        businessOrder.setDeviceTypeName(deviceOrder.getBatteryTypeName());      //默认电池类型
        if(StringTools.isNotBlank(deviceOrder.getPortableBatterySn())) {
            businessOrder.setDeviceSn(deviceOrder.getPortableBatterySn());
        }else{
            businessOrder.setDeviceSn("---");
        }
        businessOrder.setDeviceFunCode(EDeviceFunCode.BXSCN.index());
        businessOrder.setBusinessType(EBusinessType.BXSCN.index());
        businessOrder.setCostModeName(deviceOrder.getCostModeName());  //无属性无法自动拷贝

        businessOrder.setMemberId(deviceOrder.getMemberId());
        businessOrder.setMemberName(deviceOrder.getMemberName());
        businessOrder.setAgentId(deviceOrder.getLeaseAgentId());
        businessOrder.setPlaceId(deviceOrder.getLeasePlaceId());
        businessOrder.setPlaceName(deviceOrder.getLeasePlaceName());
        businessOrder.setProvince(deviceOrder.getLeaseProvince());
        businessOrder.setCity(deviceOrder.getLeaseCity());
        businessOrder.setCityArea(deviceOrder.getLeaseCityArea());
        businessOrder.setState(MemberBusinessOrderEnum.State.Working.index());

        if (BXSCNOrderEnum.PayState.Cancel.index().equals(deviceOrder.getPayState())) {
            businessOrder.setState(MemberBusinessOrderEnum.State.Cancel.index());
        } else if (BXSCNOrderEnum.State.RevertFinish.index().equals(deviceOrder.getState())
                || BXSCNOrderEnum.State.LeaseFail.index().equals(deviceOrder.getState())
                || BXSCNOrderEnum.State.Close.index().equals(deviceOrder.getState())) {
            businessOrder.setState(MemberBusinessOrderEnum.State.Finish.index());
        }

        try {
            if (dao.insert(businessOrder) > 0) {
                return businessOrder;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public MemberBusinessOrder create(BXSCNShopOrder deviceOrder) throws LogicException {
        MemberBusinessOrder businessOrder = ClassTools.copy(new MemberBusinessOrder(), deviceOrder);
        businessOrder.setTitle("便携式储能电池门店订单");

        businessOrder.setDeviceTypeName(deviceOrder.getBatteryTypeName());
        if(StringTools.isNotBlank(deviceOrder.getPortableBatterySn())) {
            businessOrder.setDeviceSn(deviceOrder.getPortableBatterySn());
        }else{
            businessOrder.setDeviceSn("---");
        }
        businessOrder.setDeviceFunCode(EDeviceFunCode.BXSCN.index());
        businessOrder.setBusinessType(EBusinessType.BXSCN_SHOP.index());
        businessOrder.setCostMode(EBXSCNCostMode.Deposit.index());      //押金模式
        businessOrder.setCostModeName(EBXSCNCostMode.Deposit.note());

        businessOrder.setMemberId(deviceOrder.getMemberId());
        businessOrder.setMemberName(deviceOrder.getMemberName());
        businessOrder.setAgentId(deviceOrder.getLeaseAgentId());
        businessOrder.setPlaceId(deviceOrder.getLeasePlaceId());
        businessOrder.setPlaceName(deviceOrder.getLeasePlaceName());
        businessOrder.setProvince(deviceOrder.getLeaseProvince());
        businessOrder.setCity(deviceOrder.getLeaseCity());
        businessOrder.setCityArea(deviceOrder.getLeaseCityArea());
        businessOrder.setAreaCode(deviceOrder.getLeaseAreaCode());
        businessOrder.setState(MemberBusinessOrderEnum.State.Working.index());

        if (BXSCNShopOrderEnum.PayState.Cancel.index().equals(deviceOrder.getPayState())
                || CDCZOrderEnum.State.Fail.index().equals(deviceOrder.getState())) {
            businessOrder.setState(MemberBusinessOrderEnum.State.Cancel.index());
        } else if (BXSCNShopOrderEnum.State.RevertFinish.index().equals(deviceOrder.getState())
                || BXSCNShopOrderEnum.State.RevertClose.index().equals(deviceOrder.getState())
                || BXSCNShopOrderEnum.State.LeaseTimeout.index().equals(deviceOrder.getState())
                || BXSCNShopOrderEnum.State.LeaseClose.index().equals(deviceOrder.getState())
                || BXSCNShopOrderEnum.State.Close.index().equals(deviceOrder.getState())) {
            businessOrder.setState(MemberBusinessOrderEnum.State.Finish.index());
        }

        try {
            if (dao.insert(businessOrder) > 0) {
                return businessOrder;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public boolean refundMoney(String tradeNo, Integer refundMoney) {
        MemberBusinessOrder businessOrder = new MemberBusinessOrder();
        businessOrder.setTradeNo(tradeNo);
        businessOrder.setPayMoney(refundMoney);
        try {
            return dao.updateNotNullAndReduce(businessOrder, "payMoney") > 0;
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return false;
    }

    public boolean finish(String tradeNo, Long money, Integer payMoney, Long walletMoney,OperateInfo operateInfo) {
    	MemberBusinessOrder businessOrder = getByTradeNo(tradeNo);
    	if(businessOrder != null && !MemberBusinessOrderEnum.State.Finish.index().equals(businessOrder.getState())) {
    		Conditions condition = new Conditions(MemberBusinessOrder.class);
    		condition.and().is("tradeNo", tradeNo);
    		condition.and().is("state", businessOrder.getState());
    		
	        MemberBusinessOrder updateEntity = new MemberBusinessOrder();
	        updateEntity.setState(MemberBusinessOrderEnum.State.Finish.index());
	        updateEntity.setMoney(money);
	        updateEntity.setPayMoney(payMoney);
	        updateEntity.setWalletMoney(walletMoney);
	
	        boolean flag = false;
	        JdbcSession.begin();
	        try {
	            if (dao.updateNotNull(updateEntity,condition) > 0) {
	                if (BusinessOrderUserService.self(dao.getDate()).updateState(tradeNo,
	                        MemberBusinessOrderEnum.State.Finish.index())) {
	                    JdbcSession.commit();
	                    flag = true;
	                }
	            }
	        } catch (SQLException e) {
	            log.error(e.getMessage(), e);
	        } finally {
	            JdbcSession.end();
	        }
	        
	        if(flag) {
	        	//检查是否开启积分
	        	BusinessConfig config = ConfigUtils.getBusinessConfig();
	        	if(config != null && config.getCanVirtualMoney()) {
	        		try {
	        			operateInfo.setOperateNote(businessOrder.getTradeNo() + "订单完成赠送");
	        			//积分计算方式 1元 = 100个虚拟币
	        			Integer vmoney = NumberTools.changeMoney(NumberTools.changeMoneyLi(money));			
	        			MemberWalletService.self().addVMoney(businessOrder.getMemberId(), vmoney.longValue(), operateInfo);
					} catch (LogicException e) {
						log.error("修改会员虚拟金额失败，" + e.getMessage(), e);
					}
	        	}
	        	return true;
	        }
    	}else {
    		log.error("未找到{{0}}会员订单，完成订单失败", tradeNo);
    	}
        return false;
    }

    public boolean cancel(String tradeNo, Long money, Integer payMoney, Long walletMoney){
        MemberBusinessOrder businessOrder = new MemberBusinessOrder();
        businessOrder.setTradeNo(tradeNo);
        businessOrder.setState(MemberBusinessOrderEnum.State.Cancel.index());
        businessOrder.setMoney(money);
        businessOrder.setPayMoney(payMoney);
        businessOrder.setWalletMoney(walletMoney);

        JdbcSession.begin();
        try {
            if (dao.updateNotNull(businessOrder) > 0) {
                if (BusinessOrderUserService.self(dao.getDate()).updateState(tradeNo,
                        MemberBusinessOrderEnum.State.Cancel.index())) {
                    JdbcSession.commit();
                    return true;
                }
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        } finally {
            JdbcSession.end();
        }
        return false;
    }

    public boolean addUseMoney(String tradeNo, Long walletMoney) {
        if (StringTools.isNotBlank(tradeNo) && walletMoney != null) {
            MemberBusinessOrder updateEntity = new MemberBusinessOrder();
            updateEntity.setTradeNo(tradeNo);
            updateEntity.setMoney(walletMoney);
            updateEntity.setWalletMoney(walletMoney);

            try {
                return dao.updateNotNullAndInc(updateEntity, "money", "walletMoney") > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return false;
    }

    public boolean updateDeviceSn(String tradeNo,String deviceTypeName, String deviceSn) {
        if (StringTools.isNotBlank(tradeNo) && StringTools.isNotBlank(deviceSn)) {
            MemberBusinessOrder updateEntity = new MemberBusinessOrder();
            updateEntity.setTradeNo(tradeNo);
            updateEntity.setDeviceTypeName(deviceTypeName);
            updateEntity.setDeviceSn(deviceSn);

            try {
                if (dao.updateNotNull(updateEntity) > 0) {
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return false;
    }

    public boolean forceUpdateMoney(String tradeNo,Long money,Integer payMoney){
        if(StringTools.isNotBlank(tradeNo) && (money != null || payMoney != null)){
            MemberBusinessOrder updateEntity = new MemberBusinessOrder();
            updateEntity.setTradeNo(tradeNo);
            updateEntity.setMoney(money);
            updateEntity.setPayMoney(payMoney);

            try {
                return dao.updateNotNull(updateEntity) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

}
